﻿#include "EditorEmptyAssetPageViewModel.h"

#include "Pages/EditorPageModel.h"
#include "Widgets/Windows/FileDialog.h"

#include "Texture/Texture2D.h"
#include "Mesh/StaticMesh.h"
#include "Mesh/StaticMeshUtils.h"
#include "Material/Material.h"
#include "Material/MaterialSubsystem.h"
#include "Scene/Scene.h"

#include "Project/ProjectModel.h"
#include "Project/ProjectViewModel.h"
#include "Asset/AssetSubsystem.h"
#include "Framework/Editor.h"
#include "File/FileUtils.h"

#include "Scene/StaticMeshComponent.h"
#include "Scene/DirectionalLightComponent.h"
#include "Scene/CameraComponent.h"
#include "Scene/InputComponent.h"

#include "Asset/EngineDefaultPackage.h"
#include "Asset/EditorDefaultPackage.h"
#include "Asset/ProjectAssetSubsystem.h"

#include "Window/EditorWindowGroupModel.h"

#include "Output/Console.h"

#include "Material/Material.h"
#include "MaterialGraph/MaterialGraphModel.h"
#include "MaterialGraph/BRDFNode/MaterialBRDFNodeModel.h"

#include "Audio/AudioSubsystem.h"
#include "Audio/Audio.h"

void REditorEmptyAssetPageViewModel::BindModel(TSharedObjectPtr<REditorPageModel> InModel)
{
    Super::BindModel(InModel);

    Model= InModel;

    //TODO add icon
    Icon= nullptr;
}

TSharedObjectPtr<RTexture2D> REditorEmptyAssetPageViewModel::GetIcon() const
{
    return Icon;
}

CString REditorEmptyAssetPageViewModel::GetTitle() const
{
    return Model->GetFileName();
}

void REditorEmptyAssetPageViewModel::ImportImage()
{
    //open file dialog to select  a image file
    auto Files=WH::CreateOpenFileDialog(
        U"选择图片",
        SPaths::GetWorkingDirectory(),
        { U".png",U".jpg",U".jpeg",U".bmp" }
    );

    if(Files.Empty())
    {
        //user cancel
        return;
    }

    SPath FilePath=Files[0];

    auto Texture=RTexture2D::CreateFromImage(FilePath);
    assert(Texture && "create texture failed");
    CString AssetName=Model->GetFilePath().GetBaseFileName();
    Texture->SetRawName(AssetName);

    auto Thumbnail= RTexture2D::Resize(Texture,SIntPoint(48,48));

    auto AssetPackage=REditor::Get()->GetSubsystem<RProjectModel>()->GetAssetPackage().GetValue();

    CString PathInPackageString=SAssetPath::AbstractFolderPathInPackage(
            AssetPackage.Path
            ,Model->GetFilePath()
        );

    //delete the old asset file,beacuse we will import a new one
    //and ImportObject() might make a different file name if the file name is already exist
    SFileUtils::DeleteFile(Model->GetFilePath());



    auto Result=RAssetSubsystem::Get()->ImportObject(
        Texture
        ,nullptr
        ,Thumbnail
        ,AssetPackage.Name
        ,PathInPackageString
        );

    SProjectAssetInfo AssetInfo;
    AssetInfo.Path=Model->GetFilePath();
    AssetInfo.ReferencePath=Result.AssetPath;
    AssetInfo.AssetHead=Result.Head;
    RProjectViewModel::Get()->GetSubsystem<RProjectAssetSubsystem>()
        ->RegisterAssetInfo(AssetInfo.Path,AssetInfo);

    //reopen the page
    REditorWindowGroupModel::Get()->ReopenPage(Model);
}

void REditorEmptyAssetPageViewModel::ImportMesh()
{
    //open file dialog to select  a image file
    auto Files=WH::CreateOpenFileDialog(
        U"选择glb模型",
        SPaths::GetWorkingDirectory(),
        { U".glb"}
    );

    if(Files.Empty())
    {
        //user cancel
        return;
    }

    SPath FilePath=Files[0];

    auto Mesh=RStaticMeshUtils::LoadFromGLTF(FilePath);
    assert(Mesh && "create mesh failed");
    CString AssetName=Model->GetFilePath().GetBaseFileName();
    Mesh->SetRawName(AssetName);

    auto AssetPackage=REditor::Get()->GetSubsystem<RProjectModel>()->GetAssetPackage().GetValue();
    CString PathInPackageString=SAssetPath::AbstractFolderPathInPackage(
            AssetPackage.Path
            ,Model->GetFilePath()
        );
    //delete the old asset file,beacuse we will import a new one
    //and ImportObject() might make a different file name if the file name is already exist
    SFileUtils::DeleteFile(Model->GetFilePath());

    auto Result=RAssetSubsystem::Get()->ImportObject(
        Mesh
        ,nullptr
        ,nullptr
        ,AssetPackage.Name
        ,PathInPackageString
        );

    SProjectAssetInfo AssetInfo;
    AssetInfo.Path=Model->GetFilePath();
    AssetInfo.ReferencePath=Result.AssetPath;
    AssetInfo.AssetHead=Result.Head;
    RProjectViewModel::Get()->GetSubsystem<RProjectAssetSubsystem>()
        ->RegisterAssetInfo(AssetInfo.Path,AssetInfo);

    //reopen the page
    REditorWindowGroupModel::Get()->ReopenPage(Model);    

}

void REditorEmptyAssetPageViewModel::ImportAudio()
{
    //open file dialog to select  a image file
    auto Files=WH::CreateOpenFileDialog(
        U"选择音频文件",
        SPaths::GetWorkingDirectory(),
        { U".wav"}
    );

    if(Files.Empty())
    {
        //user cancel
        return;
    }

    SPath FilePath=Files[0];
    auto Audio=RAudioSubsystem::GetInstance()->LoadWavFile(FilePath);

    if(!Audio)
    {
        RConsole::PrintLine(U"导入音频失败");
        return;
    }

    CString AssetName=Model->GetFilePath().GetBaseFileName();
    Audio->SetRawName(AssetName);

    auto AssetPackage=REditor::Get()->GetSubsystem<RProjectModel>()->GetAssetPackage().GetValue();
    CString PathInPackageString=SAssetPath::AbstractFolderPathInPackage(
            AssetPackage.Path
            ,Model->GetFilePath()
        );
    //delete the old asset file,beacuse we will import a new one
    //and ImportObject() might make a different file name if the file name is already exist
    SFileUtils::DeleteFile(Model->GetFilePath());

    auto Result=RAssetSubsystem::Get()->ImportObject(
        Audio
        ,nullptr
        ,nullptr
        ,AssetPackage.Name
        ,PathInPackageString
        );

    SProjectAssetInfo AssetInfo;
    AssetInfo.Path=Model->GetFilePath();
    AssetInfo.ReferencePath=Result.AssetPath;
    AssetInfo.AssetHead=Result.Head;
    RProjectViewModel::Get()->GetSubsystem<RProjectAssetSubsystem>()
        ->RegisterAssetInfo(AssetInfo.Path,AssetInfo);

    //reopen the page
    REditorWindowGroupModel::Get()->ReopenPage(Model);
}

void REditorEmptyAssetPageViewModel::CreateMaterial()
{
    TSharedObjectPtr<RMaterial> Material=
        RMaterialSubsystem::Get()->CreateDefaultMaterial();
    TSharedObjectPtr<RMaterialGraphModel> MaterialGraph=NewObject<RMaterialGraphModel>(Material);

    //create output node
    //auto OutputNode=NewObject<RMaterialBRDFNodeModel>(MaterialGraph); 
    MaterialGraph->AddNode(RMaterialBRDFNodeModel::StaticClass(),SVec2(0,0)); 

    //save   
    CString AssetName=Model->GetFilePath().GetBaseFileName();
    Material->SetRawName(AssetName);

    auto AssetPackage=REditor::Get()->GetSubsystem<RProjectModel>()->GetAssetPackage().GetValue();
    CString PathInPackageString=SAssetPath::AbstractFolderPathInPackage(
            AssetPackage.Path
            ,Model->GetFilePath()
        );
    //delete the old asset file,beacuse we will import a new one
    //and ImportObject() might make a different file name if the file name is already exist
    SFileUtils::DeleteFile(Model->GetFilePath());

    auto Result=RAssetSubsystem::Get()->ImportObject(
        Material
        ,MaterialGraph
        ,nullptr
        ,AssetPackage.Name
        ,PathInPackageString
        );
    
    SProjectAssetInfo AssetInfo;
    AssetInfo.Path=Model->GetFilePath();
    AssetInfo.ReferencePath=Result.AssetPath;
    AssetInfo.AssetHead=Result.Head;
    RProjectViewModel::Get()->GetSubsystem<RProjectAssetSubsystem>()
        ->RegisterAssetInfo(AssetInfo.Path,AssetInfo);

    //reopen the page
    REditorWindowGroupModel::Get()->ReopenPage(Model);    
}

void REditorEmptyAssetPageViewModel::CreateScene()
{
    RScenePtr Scene= NewObject<RScene>();
    {
        //add a default camera
        auto Light=Scene->NewNode<RSceneNode>();
        Light->SetNodeName(U"DirectionalLight");
        Light->SetWorldPosition(SVec3(0,0,0)); //any where is ok
        Light->SetWorldRotation(SQuat::FromEuler(SVec3(CMathBase::DegreeToRadian(-45.f),0,0)));
        {
            auto LightComponent=Light->CreateAndAddComponent<RDirectionalLightComponent>();
        }

        auto GreyFloor=Scene->NewNode<RSceneNode>();
        GreyFloor->SetNodeName(U"GreyFloor");
        GreyFloor->SetWorldPosition(SVec3(0,0,-1));
        GreyFloor->SetScale(SVec3(10,10,1));
        {
            auto MeshComponent=GreyFloor->CreateAndAddComponent<RStaticMeshComponent>();
            MeshComponent->SetStaticMesh(REngineDefaultPackage::Get()->GetCubeMesh());
            MeshComponent->SetMaterials({REngineDefaultPackage::Get()->GetDefaultMaterial()});

        }

        auto Camera=Scene->NewNode<RSceneNode>();
        Camera->SetNodeName(U"Camera");
        auto CameraComponent=Camera->CreateAndAddComponent<RCameraComponent>();
        Camera->SetWorldPosition(SVec3(0,-3,2));
        Camera->SetWorldRotation(SQuat::FromEuler(SVec3(CMathBase::DegreeToRadian(-30.f),0,0))); 
    }

    CString AssetName=Model->GetFilePath().GetBaseFileName();
    Scene->SetRawName(AssetName);

    auto AssetPackage=REditor::Get()->GetSubsystem<RProjectModel>()->GetAssetPackage().GetValue();
    CString PathInPackageString=SAssetPath::AbstractFolderPathInPackage(
            AssetPackage.Path
            ,Model->GetFilePath()
        );
    //delete the old asset file,beacuse we will import a new one
    //and ImportObject() might make a different file name if the file name is already exist
    SFileUtils::DeleteFile(Model->GetFilePath());

    auto Result=RAssetSubsystem::Get()->ImportObject(
        Scene
        ,nullptr
        ,nullptr
        ,AssetPackage.Name
        ,PathInPackageString
        );

    SProjectAssetInfo AssetInfo;
    AssetInfo.Path=Model->GetFilePath();
    AssetInfo.ReferencePath=Result.AssetPath;
    AssetInfo.AssetHead=Result.Head;
    RProjectViewModel::Get()->GetSubsystem<RProjectAssetSubsystem>()
        ->RegisterAssetInfo(AssetInfo.Path,AssetInfo);

    //reopen the page
    REditorWindowGroupModel::Get()->ReopenPage(Model);
}
